Completed
Push — master ( b6e14c...5630cf )
by
unknown
53s
created

Model.js ➔ ... ➔ ???   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
c 3
b 0
f 0
nc 1
dl 0
loc 1
ccs 1
cts 1
cp 1
crap 1
rs 10
nop 1
1
/**
2
 * Abstract Model class interacting with MongoDB
3
 *
4
 * @since 1.0.0
5
 */
6
7 1
const co = require('co');
8 1
const mongodb = require('mongodb');
9 1
const config = require('../config/server.config');
10 1
const NotifierError = require('../common/Error');
11
12 1
const MongoClient = mongodb.MongoClient;
13 1
const ObjectID = mongodb.ObjectID;
14 1
const url = process.env.MONGODB_URI || config.defaults.mongoDBUrl;
15 1
const logger = require('winston');
16
17
/**
18
 * @class
19
 * @classdesc basic interactions with selected collection
20
 */
21
class Model {
22
23
  constructor(collection, indexes) {
24 4
    if (new.target === Model) {
25
      throw new TypeError('Cannot construct Model instances directly');
26
    }
27
28 4
    this.collection = collection || this.constructor.name.toLowerCase();
29
30 4
    if (indexes instanceof Array) {
31 2
      this.runQuery(col => col.createIndexes(indexes))
32 2
        .then(() => logger.log(`[DB] ${this.collection}'s index creation is successfully done.`))
33
        .catch(error => logger.error(`[DB] ${this.collection}'s index creation is failed.`, error));
34
    }
35
  }
36
37
  runQuery(fn) {
38 29
    const self = this;
39 29
    return co(function* () {
40 29
      const db = yield MongoClient.connect(url);
41 29
      const collection = db.collection(self.collection);
42 29
      const result = yield fn.call(self, collection);
43 29
      yield db.close();
44 29
      return result;
45
    }).catch((err) => {
46
      throw err;
47
    });
48
  }
49
50
  find(query, sort, skip, limit) {
51 6
    if (query && query._id) {
52 3
      query._id = ObjectID(query._id);
53
    }
54 6
    return this.runQuery((collection) => {
55 6
      const cursor = collection.find(query || {}).sort(sort || {});
56 6
      if (typeof skip !== 'undefined' || typeof limit !== 'undefined') {
57
        cursor.skip(skip).limit(limit);
58
      }
59 6
      return cursor.toArray();
60 6
    }).then(list => list.map((item) => {
61 7
      item._id = item._id.toHexString();
62 7
      return item;
63
    })).catch((error) => {
64
      logger.error(error);
65
      throw new NotifierError(NotifierError.Types.DB, {}, error);
66
    });
67
  }
68
69
  count(query) {
70 3
    return this.runQuery(collection => collection.count(query || {}))
71
      .catch((error) => {
72
        logger.error(error);
73
        throw new NotifierError(NotifierError.Types.DB, {}, error);
74
      });
75
  }
76
77
  add(model) {
78 10
    return this.runQuery(collection => collection.insertOne(model))
79
      .then((result) => {
80 10
        let data = result.ops;
81 10
        if (data) {
82 10
          data = result.ops.map(d => Object.assign({}, d, { _id: d._id.toHexString() }));
83
        }
84 10
        return { data, count: result.result.n };
85
      })
86
      .catch((error) => {
87
        logger.error(error);
88
        throw new NotifierError(NotifierError.Types.DB, {}, error);
89
      });
90
  }
91
92
  update(id, model) {
93 3
    return this.updateWithQuery({ _id: ObjectID(id) }, model);
94
  }
95
96
  updateWithQuery(query, model) {
97 4
    return this.runQuery(collection => collection.findOneAndUpdate(query, { $set: model }))
98 4
      .then(result => ({ data: [{ _id: result.value._id.toHexString() }], count: 1 }))
99
      .catch((error) => {
100
        logger.error(error);
101
        throw new NotifierError(NotifierError.Types.DB, {}, error);
102
      });
103
  }
104
105
  remove(id) {
106 4
    return this.runQuery(collection => collection.deleteOne({ _id: ObjectID(id) }))
107 4
      .then(result => ({ data: [{ _id: id }], count: result.result.n }))
108
      .catch((error) => {
109
        logger.error(error);
110
        throw new NotifierError(NotifierError.Types.DB, {}, error);
111
      });
112
  }
113
}
114
115
module.exports = Model;
116